#include "Math.h"

namespace Math
{
	void SetScale(glm::mat4& transform, float scale)
	{
		transform[0][0] = scale;
		transform[1][1] = scale;
		transform[2][2] = scale;
	}

	void SetScale(glm::mat4& transform, const glm::vec3& scale)
	{
		transform[0][0] = scale.x;
		transform[1][1] = scale.y;
		transform[2][2] = scale.z;
	}

	void SetRotation(glm::mat4& transform, const glm::vec3& rotation)
	{
		transform = glm::rotate(transform, glm::radians(rotation.x), glm::vec3(1.0f, 0.0f, 0.0f));
		transform = glm::rotate(transform, glm::radians(rotation.y), glm::vec3(0.0f, 1.0f, 0.0f));
		transform = glm::rotate(transform, glm::radians(rotation.z), glm::vec3(0.0f, 0.0f, 1.0f));
	}

	void SetTranslation(glm::mat4& transform, const glm::vec3& translation)
	{
		transform[3][0] = translation.x;
		transform[3][1] = translation.y;
		transform[3][2] = translation.z;
	}

	glm::vec3 GetScale(const glm::mat4& transform)
	{
		glm::vec3 scale = glm::vec3(transform[0][0], transform[1][1], transform[2][2]);
		return scale;
	}

	glm::vec3 GetRotation(const glm::mat4& transform)
	{
		glm::vec3 rotation = glm::eulerAngles(glm::quat_cast(transform));
		return rotation;
	}

	glm::mat4 Mat4FromTRS(const glm::vec3& translation, const glm::vec3& rotation, const glm::vec3& scale)
	{
		glm::mat4 transform = glm::mat4(1.0f);
		SetScale(transform, scale);
		SetRotation(transform, rotation);
		SetTranslation(transform, translation);
		return transform;
	}

	glm::mat3x4 GlmToVkMat(const glm::mat4& transform)
	{
		glm::mat3x4 result;
		// glm::mat4 modelMatrix = glm::transpose(transform);
		// memcpy(&result, &modelMatrix, sizeof(glm::mat3x4));

		result[0][0] = transform[0][0];
		result[0][1] = transform[1][0];
		result[0][2] = transform[2][0];
		result[0][3] = transform[3][0];
		result[1][0] = transform[0][1];
		result[1][1] = transform[1][1];
		result[1][2] = transform[2][1];
		result[1][3] = transform[3][1];
		result[2][0] = transform[0][2];
		result[2][1] = transform[1][2];
		result[2][2] = transform[2][2];
		result[2][3] = transform[3][2];

		return result;
	}

	void SinCos(float angle, float& sin, float& cos)
	{
		float angleRadians = angle * M_DEGTORAD;
		sin = sinf(angleRadians);
		cos = cosf(angleRadians);
	}

	uint32 nChoosek(uint32 n, uint32 k)
	{
		if (k > n)
			return 0;
		if (k * 2 > n)
			k = n - k;
		if (k == 0)
			return 1;

		uint32 result = n;
		for (int i = 2; i <= k; ++i)
		{
			result *= (n - i + 1);
			result /= i;
		}
		return result;
	}
}